package Solutions;

import java.util.Queue;
import java.util.Stack;

/**
 * @Classname DecodeWays
 * @Description TODO
 * @Date 2021/6/14 20:29
 * @Created by ASUS
 * 一条包含字母 A-Z 的消息通过以下映射进行了 编码 ：
 *
 * 'A' -> 1
 * 'B' -> 2
 * ...
 * 'Z' -> 26
 *
 * 要 解码 已编码的消息，所有数字必须基于上述映射的方法，反向映射回字母（可能有多种方法）。例如，"11106" 可以映射为：
 *
 *     "AAJF" ，将消息分组为 (1 1 10 6)
 *     "KJF" ，将消息分组为 (11 10 6)
 *
 * 注意，消息不能分组为  (1 11 06) ，因为 "06" 不能映射为 "F" ，这是由于 "6" 和 "06" 在映射中并不等价。
 *
 * 给你一个只含数字的 非空 字符串 s ，请计算并返回 解码 方法的 总数 。
 *
 * 题目数据保证答案肯定是一个 32 位 的整数。
 *
 *
 *
 * 示例 1：
 *
 * 输入：s = "12"
 * 输出：2
 * 解释：它可以解码为 "AB"（1 2）或者 "L"（12）。
 *
 * 示例 2：
 *
 * 输入：s = "226"
 * 输出：3
 * 解释：它可以解码为 "BZ" (2 26), "VF" (22 6), 或者 "BBF" (2 2 6) 。
 *
 * 来源：力扣（LeetCode）
 * 链接：https://leetcode-cn.com/problems/decode-ways
 * 著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。
 */
public class DecodeWays {
    /***
     * 执行结果：
     * 通过
     * 显示详情
     *
     * 添加备注
     * 执行用时：1 ms, 在所有 Java 提交中击败了100.00% 的用户
     * 内存消耗：36.4 MB, 在所有 Java 提交中击败了95.97% 的用户
     */
    public int numDecodings(String s) {
        int m = s.length();
        int[] dp = new int[m];
        if (s.charAt(0) == '0') return 0;
        dp[0] = 1;
        for (int i = 1; i < m; i++) {
            if (s.charAt(i - 1) != '0') {
                int tmp = getInt(s.charAt(i-1), s.charAt(i));
                if (tmp <= 26) {
                    if (i - 2 >= 0) {
                        dp[i] += dp[i - 2];
                    } else {
                        dp[i]++;
                    }
                }
            }
            if (s.charAt(i) == '0') continue;
            dp[i] += dp[i-1];
        }
        return dp[m-1];

    }

    private int getInt(char charAt, char charAt1) {
        return (charAt - '0') * 10 + charAt1 - '0';
    }

    public static void main(String[] args) {
//        System.out.println(new DecodeWays().numDecodings("11106"));
        System.out.println(new DecodeWays().decodeString("3[a]2[bc]"));
    }

    /***
     * 示例 1：
     *
     * 输入：s = "3[a]2[bc]"
     * 输出："aaabcbc"
     *
     * 示例 2：
     *
     * 输入：s = "3[a2[c]]"
     * 输出："accaccacc"
     *
     * 来源：力扣（LeetCode）
     * 链接：https://leetcode-cn.com/problems/decode-string
     * 著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。
     *
     * 执行结果：
     * 通过
     * 显示详情
     *
     * 添加备注
     * 执行用时：0 ms, 在所有 Java 提交中击败了100.00% 的用户
     * 内存消耗：36.2 MB, 在所有 Java 提交中击败了93.87% 的用户
     */
    public String decodeString(String str) {
        if (str.equals("")) return "";
        char[] chars = str.toCharArray();
        StringBuilder number = new StringBuilder();
        StringBuilder answer = new StringBuilder();
        int num;
        for (int i = 0; i < str.length(); i++) {
            while (chars[i] >= '0' && chars[i] <= '9') number.append(chars[i++]);
            if (number.length() != 0) {
                num = Integer.parseInt(number.toString());
                number.delete(0, number.length());
                int end = getIndex(str, i);
                String tmp = str.substring(i + 1, end );
                String append_substring = decodeString(tmp);
                answer.append(String.valueOf(append_substring).repeat(Math.max(0, num)));
                i = end;
            } else {
                answer.append(chars[i]);
            }
        }
        return answer.toString();
    }

    private int getIndex(String str, int start) {
        int amount = 0;
        for (int i = start; i < str.length(); i++) {
            if (str.charAt(i) == '[') amount++;
            else if (str.charAt(i) == ']') {
                if (amount == 1) return i;
                else amount--;
            }
        }
        return -1;
    }
}
